package com.hzw.saas.service.rbac.service;

import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.rbac.IPermissionService;
import com.hzw.saas.api.rbac.bo.PermissionStructBO;
import com.hzw.saas.api.rbac.constants.RbacConsts;
import com.hzw.saas.service.rbac.IRolePermissionService;
import com.hzw.saas.service.rbac.mapper.RolePermissionMapper;
import com.hzw.saas.service.rbac.model.RolePermission;
import cn.hutool.core.util.ArrayUtil;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author zzl
 * @since 08/30/2021
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper, RolePermission> implements IRolePermissionService {

    @Resource
    private IPermissionService permissionService;

    @Override
    public void updateRolePermissions(Integer sys, String roleId, List<String> permIds) {
        if (ArrayUtil.isEmpty(permIds))
            return;
        // 删除原关联数据
        super.lambdaUpdate()
            .eq(RolePermission::getSys, sys)
            .eq(RolePermission::getRoleId, roleId)
            .remove();
        // 创建新关联数据
        List<RolePermission> rolePermissions = new ArrayList<>();
        Set<String> permIds2Add = this.assembleSupIds(sys, permIds);
        for (String permId : permIds2Add) {
            rolePermissions.add(new RolePermission(sys, roleId, permId));
        }
        super.saveBatch(rolePermissions);
    }

    /**
     * 获取权限及所有父级权限ID
     * 无效ID会被舍弃
     */
    private Set<String> assembleSupIds(Integer sys, List<String> permIds) {
        Set<String> result = new HashSet<>();
        List<PermissionStructBO> permissions = permissionService.listStruct(sys);
        Map<String, PermissionStructBO> permMap = permissions.stream()
            .collect(Collectors.toMap(PermissionStructBO::getPid, p -> p, (k1, k2) -> k1));
        for (String permId : permIds) {
            this.assembleSupIds(result, permMap, permId);
        }
        return result;
    }

    private void assembleSupIds(Set<String> result, Map<String, PermissionStructBO> permissions, String permId) {
        if (result.contains(permId)) {
            return;
        }
        PermissionStructBO permission = permissions.get(permId);
        if (Objects.isNull(permission)) {
            return;
        } else {
            result.add(permId);
        }
        if (!Objects.equals(permission.getSupId(), RbacConsts.ROOT_PERMISSION_SUP_ID)) {
            this.assembleSupIds(result, permissions, permission.getSupId());
        }
    }
}
